from datetime import timedelta, timezone
from fastapi import APIRouter,BackgroundTasks
from app.controllers.system.user import user_controller
from app.core.ctx import CTX_USER_ID
from app.core.dependency import DependAuth, DependPermisson
from app.models.admin import Api, Menu, Role, User
from app.schemas.base import Fail, Success
from app.schemas.login import *
from app.schemas.users import UpdatePassword
from app.settings import settings
from app.utils.jwt import create_access_token
from app.utils.password import get_password_hash, verify_password
from app.controllers.orders.list import orders_list_controller
from fastapi import  WebSocket, WebSocketDisconnect
from app.core.websocket_manager import manager
import subprocess
from app.utils.mysqlbak import MySQLBackup


base_router = APIRouter()
from tortoise.expressions import Q


@base_router.post("/access_token", summary="获取token")
async def login_access_token(credentials: CredentialsSchema):
    user: User = await user_controller.authenticate(credentials)
    await user_controller.update_last_login(user.id)
    access_token_expires = timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)
    expire = datetime.now(timezone.utc) + access_token_expires

    data = JWTOut(
        access_token=create_access_token(
            data=JWTPayload(
                user_id=user.id,
                username=user.username,
                is_superuser=user.is_superuser,
                exp=expire,
            )
        ),
        username=user.username,
    )
    return Success(data=data.model_dump())


@base_router.get("/userinfo", summary="查看用户信息", dependencies=[DependAuth])
async def get_userinfo():
    user_id = CTX_USER_ID.get()
    user_obj = await user_controller.get(id=user_id)
    data = await user_obj.to_dict(exclude_fields=["password"])
    data["avatar"] = "app/upload/admin/12345678.png"
    return Success(data=data)


@base_router.get("/usermenu", summary="查看用户菜单", dependencies=[DependAuth])
async def get_user_menu():
    user_id = CTX_USER_ID.get()
    user_obj = await User.filter(id=user_id).first()
    menus: list[Menu] = []
    res = []
    if user_obj.is_superuser:
        menus = await Menu.all()
    else:
        role_objs: list[Role] = await user_obj.roles
        for role_obj in role_objs:
            menu = await role_obj.menus
            menus.extend(menu)
        menus = list(set(menus))

    ##一级栏目
    parent_menus: list[Menu] = []
    for menu in menus:
        if menu.parent_id == 0:
            parent_menus.append(menu)
    ##遍历一级栏目,放入二级栏目
    for parent_menu in parent_menus:
        parent_menu_dict = await parent_menu.to_dict()
        parent_menu_dict["children"] = []
        for menu in menus:
            if menu.parent_id == parent_menu.id:
                ##此处就要放入三级栏目到menu这个二级里面
                menu_dict = await menu.to_dict()
                menu_dict["children"] = []
                for three in menus:
                    if three.parent_id == menu.id:
                        menu_dict["children"].append(await three.to_dict())
                parent_menu_dict["children"].append(menu_dict)
        res.append(parent_menu_dict)

    return Success(data=res)


@base_router.get("/userapi", summary="查看用户API", dependencies=[DependAuth])
async def get_user_api():
    user_id = CTX_USER_ID.get()
    user_obj = await User.filter(id=user_id).first()
    if user_obj.is_superuser:
        api_objs: list[Api] = await Api.all()
        apis = [api.method.lower() + api.path for api in api_objs]
        return Success(data=apis)
    role_objs: list[Role] = await user_obj.roles
    apis = []
    for role_obj in role_objs:
        api_objs: list[Api] = await role_obj.apis
        apis.extend([api.method.lower() + api.path for api in api_objs])
    apis = list(set(apis))
    return Success(data=apis)


@base_router.post("/update_password", summary="修改密码", dependencies=[DependAuth])
async def update_user_password(req_in: UpdatePassword):
    user_id = CTX_USER_ID.get()
    user = await user_controller.get(user_id)
    verified = verify_password(req_in.old_password, user.password)
    if not verified:
        return Fail(msg="旧密码验证错误！")
    user.password = get_password_hash(req_in.new_password)
    await user.save()
    return Success(msg="修改成功")


@base_router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            # 待接收前端的消息（可以是心跳或其他信息）
            await websocket.receive_text()
    except WebSocketDisconnect:
        await manager.disconnect(websocket)


@base_router.get("/test_ws", summary="测试WebSocket消息", dependencies=[DependAuth])
async def test_WebSocket():
    await manager.notify_clients(f"您有一个新的订单:12345")
    return Success()


@base_router.post("/gitee_push", summary="测试gitee")
async def gitee_push():
    try:
        script_path = "/www/wwwroot/xiyou/xiyou-admin/.git/hooks/post-receive"
        result = subprocess.run([script_path], capture_output=True, text=True)
        if result.returncode != 0:
            return Fail(msg="执行失败！")
        return Success(msg="git拉取成功")
    except Exception as e:
        return Fail(msg="错误")

@base_router.post("/mysql_bak", summary="备份数据库")
async def mysql_bak(
    back_tasks: BackgroundTasks,
):
    # 创建备份对象
    backup = MySQLBackup()
    back_tasks.add_task(backup.backup)
    return Success(msg="备份成功")


@base_router.get("/workbench", summary="工作台", dependencies=[DependAuth])
async def get_workbench():
    row1_week_price, row1_week_cnt = await orders_list_controller.get_weekly_order_totals()
    row1_all_price = await orders_list_controller.get_all_price()
    if row1_week_price[5] > 0:
        row1_bl = (row1_week_price[6] - row1_week_price[5]) / row1_week_price[5] * 100
    else:
        row1_bl = 100

    row1_left = {
        "price": row1_week_price[6],
        "all_price": row1_all_price,
        "bl": f"{row1_bl}%",
        "map": [
            {"name": '小程序', "type": 'line', "data": row1_week_price, },
            {"name": '线下', "type": 'line', "data": [0, 0, 0, 0, 0, 0, 0], }
        ]
    }
    row1_all_cnt = await orders_list_controller.get_all_cnt()
    if row1_week_cnt[5] > 0:
        row1_bl2 = (row1_week_cnt[6] - row1_week_cnt[5]) / row1_week_cnt[5] * 100
    else:
        row1_bl2 = 100
    row1_middle = {
        "price": row1_week_cnt[6],
        "all_price": row1_all_cnt,
        "bl": f"{row1_bl2}%",
        "map": row1_week_cnt
    }
    row1_right_all = await orders_list_controller.get_weekly_uv()
    row1_right_bl = await orders_list_controller.get_uv_bl()
    row1_right = {
        "price": row1_right_all[6],
        "bl": f"{row1_right_bl}%",
        "map": row1_right_all
    }
    row2_data = await orders_list_controller.get_goods_orders_datas()
    row2 = [
        {"id": 0, "name": '库存预警', "value": row2_data[0], "path": "/goods/good"},
        {"id": 1, "name": '缺货下架', "value": row2_data[1], "path": "/goods/good"},
        {"id": 2, "name": '滞销商品', "value": row2_data[2], "path": "/goods/good"},
        {"id": 3, "name": '待发货', "value": row2_data[3], "path": "/orders/send"},
        {"id": 4, "name": '部分发货', "value": row2_data[4], "path": "/orders/send"},
        {"id": 5, "name": '已发货', "value": row2_data[5], "path": "/orders/send"},
        {"id": 6, "name": '售后', "value": row2_data[6], "path": "/orders/work"}
    ]

    row3_data = await orders_list_controller.get_monthly_order_totals()
    row3_left = {
        "data1": [
            {"value": row1_right_all[6], "name": '小程序'},
            {"value": 0, "name": 'ios'},
            {"value": 0, "name": '安卓'},
        ],
        "data2": row3_data
    }
    q = Q(status=1, is_express=0)
    row3_right_count, row3_right_list = await orders_list_controller.do_list(page=1, page_size=6, search=q)
    for orders in row3_right_list:
        orders['id'] = f"订单编号:{orders['id']}"
        if orders['type'] == 1:
            orders['status_name'] = "待制作"
        else:
            orders['status_name'] = "待发货"
    row3_right = {
        "list": row3_right_list,
        "count": row3_right_count
    }

    data = {
        "row1_left": row1_left,
        "row1_middle": row1_middle,
        "row1_right": row1_right,
        "row2": row2,
        "row3_left": row3_left,
        "row3_right": row3_right,
    }
    return Success(data=data)

